﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BPM.Service;
using BPM.Entity;
using BPM.Controllers;
using BPM;
using Moq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using BPM.Web;
using BPM.Common;

namespace WebTest
{
	public abstract class TestBase
	{
		public static void InitializeApplication()
		{
			LazyProviderFactoryHost.Factory = ServiceFactory.Instance;
			//DPHost.Context = new ControllerUserStrategy_HttpSession();
			DPHost.Context = ControllerUserStrategy_Test.Instance;

			new EntitiesInitializer().InitSysEntites();
		}

		public virtual void TestInitialize()
		{
			LogonAsAdmin();
		}

		public User CurrentUser
		{
			get
			{
				return SysUsers.Administrator;
			}
		}

		public virtual void TestCleanup()
		{
			Logout();
		}

		#region Mock Logon

		private class ControllerUserStrategy_Test : IControllerUserStrategy
		{
			public static readonly ControllerUserStrategy_Test Instance = new ControllerUserStrategy_Test();

			private ControllerUserStrategy_Test() { }

			public User CurrentUser;

			public User GetCurrentUser(HttpContextBase context)
			{
				return CurrentUser;
			}

			public void SetCurrentUser(HttpContextBase context, User value)
			{
				CurrentUser = value;
			}
		}

		protected void LogonAsAdmin()
		{
			LogonAs(SysRoles.Admin);
		}

		protected void LogonAs(Role role)
		{
			ControllerUserStrategy_Test.Instance.CurrentUser = new UserService().GetByUserName("admin");
			//CreateController<LogonController>().Logon(new BPM.ViewModel.LogonViewModel()
			//{
			//    UserName = "admin",
			//    Password = "1"
			//});
		}

		protected void Logout()
		{
			ControllerUserStrategy_Test.Instance.CurrentUser = null;
			//CreateController<LogonController>().Logout();
		}

		//private User _user = null;

		private Dictionary<string, object> _session = new Dictionary<string, object>();

		protected TController CreateController<TController>()
			where TController : BaseController, new()
		{
			var result = new TController();

			//var session = new Mock<HttpSessionStateBase>();
			//session.Setup(s => s[""]).Returns<string>(name =>
			//{
			//    object res = null;
			//    _session.TryGetValue(name, out res);
			//    return res;
			//});

			//session.Setup(ss => ss[""] = "");//.Callback<string>(
			//session.Object["haha"] = value

			//var context = new Mock<ControllerContext>();
			//context.SetupGet(c => c.HttpContext.Session).Returns(session.Object);
			//result.ControllerContext = context.Object;

			//var m = new Mock<TController>(MockBehavior.Default);
			//m.Setup(c => c.j
			//m.SetupGet(c => c.CurrentUser).Returns(() => _curUser);
			//return m.Object as TController;

			return result;
		}

		#endregion

		protected void AssertIsTrue(ActionResult res)
		{
			Assert.IsTrue(ReadResult(res));
		}
		protected Result ReadResult(ActionResult res)
		{
			return (Result)(res as JsonResult).Data;
		}

		#region Additional test attributes
		//
		// You can use the following additional attributes as you write your tests:
		//
		// Use ClassInitialize to run code before running the first test in the class
		// [ClassInitialize()]
		// public static void MyClassInitialize(TestContext testContext) { }
		//
		// Use ClassCleanup to run code after all tests in a class have run
		// [ClassCleanup()]
		// public static void MyClassCleanup() { }
		//
		// Use TestInitialize to run code before running each test 
		// [TestInitialize()]
		// public void MyTestInitialize() { }
		//
		// Use TestCleanup to run code after each test has run
		// [TestCleanup()]
		// public void MyTestCleanup() { }
		//
		#endregion

		private TestContext testContextInstance;

		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get
			{
				return testContextInstance;
			}
			set
			{
				testContextInstance = value;
			}
		}
	}
}
